﻿using System;
using System.IO;
using System.Net;
using Caliburn.Micro;

namespace MediaOwl.Common
{
    public class WebClientDownload : IResult
    {
        private readonly Uri uri;
        private readonly Action<Stream> onSuccess;
        private readonly Action<string> onSuccessAsString;
        private readonly Action<Exception> onFail;
        private readonly bool returnAsString;

        public WebClientDownload(Uri uri, Action<Stream> onSuccess, Action<Exception> onFail = null)
        {
            this.uri = uri;
            this.onSuccess = onSuccess;
            this.onFail = onFail;
            returnAsString = false;
        }

        public WebClientDownload(Uri uri, Action<string> onSuccess, Action<Exception> onFail = null)
        {
            this.uri = uri;
            onSuccessAsString = onSuccess;
            this.onFail = onFail;
            returnAsString = true;
        }

        public void Execute(ActionExecutionContext context)
        {
            var webClient = new WebClient();

            if (returnAsString)
            {
                webClient.DownloadStringCompleted += (sender, e) => OnCompleted(e);
                webClient.DownloadStringAsync(uri);
            }
            else
            {
                webClient.OpenReadCompleted += (sender, e) => OnCompleted(e);
                webClient.OpenReadAsync(uri);
            }
        }

        private void OnCompleted(DownloadStringCompletedEventArgs e)
        {
            if (e.Cancelled || e.Error != null)
            {
                if (onFail != null)
                    Caliburn.Micro.Execute.OnUIThread(() => onFail(e.Error));
            }
            else
            {
                if (onSuccess != null)
                    Caliburn.Micro.Execute.OnUIThread(() => onSuccessAsString(e.Result));
            }

            Completed(this, new ResultCompletionEventArgs { Error = e.Error, WasCancelled = false });
        }

        private void OnCompleted(OpenReadCompletedEventArgs e)
        {
            if (e.Cancelled || e.Error != null)
            {
                if (onFail != null)
                    Caliburn.Micro.Execute.OnUIThread(() => onFail(e.Error));
            }
            else
            {
                if (onSuccess != null)
                    Caliburn.Micro.Execute.OnUIThread(() => onSuccess(e.Result));
            }

            Completed(this, new ResultCompletionEventArgs { Error = e.Error, WasCancelled = false });
        }

        public event EventHandler<ResultCompletionEventArgs> Completed  = delegate { };
    }
}